home *** CD-ROM | disk | FTP | other *** search
- /*
- * viewcorr.c - Iterate the view parameters.
- *
- *
- * Author: Rod G. Bogart
- * Date: Oct 15 1990
- * Copyright (c) 1990, University of Michigan
- *
- */
- #include <stdio.h>
- #include <math.h>
- #include "GraphicsGems.h"
- #include "matrix.h"
- #include "viewcorr.h"
-
- iterate_view_parms( datapts, view_parms, num_iterations )
- ViewData *datapts;
- ViewParms *view_parms;
- int num_iterations;
- {
- Matrix errors, jacobian, corrections;
- int i,j;
- double rootmeansqr, last_rootmeansqr;
-
- /* allocate Matrix stuff */
- errors = NewMatrix(datapts->numpts*2, 1);
- jacobian = NewMatrix(datapts->numpts*2, NUM_VIEW_PARMS);
- corrections = NewMatrix(NUM_VIEW_PARMS, 1);
-
- if (num_iterations <= 0) {
- num_iterations = 10000;
- }
- last_rootmeansqr = 0.0;
- for (i = 0; i < num_iterations; i++)
- {
- measure_errors( datapts, view_parms, errors, &rootmeansqr );
- if (ABS(rootmeansqr - last_rootmeansqr) < 1E-8) {
- /* quit when rootmeansqr stays the same */
- break;
- }
- last_rootmeansqr = rootmeansqr;
- if (rootmeansqr > (0.1 * view_parms->halfx))
- /* When the error terms are large, the corrections become too
- * extreme, and knock the whole thing into outer space. Sooo,
- * shrink the error terms, to cause the corrections to happen
- * a small amount at a time. Note: dividing by the rootmeansqr
- * may be a little extreme, but it does slow down the erratic
- * behaviour.
- */
- for (j = 0; j < datapts->numpts; j++)
- {
- errors[0][j*2] /= rootmeansqr;
- errors[0][j*2+1] /= rootmeansqr;
- }
- build_jacobian( datapts, view_parms, jacobian );
- find_corrections( datapts, jacobian, errors, corrections );
- apply_corrections( corrections, view_parms );
- }
- FreeMatrix(errors, 1);
- FreeMatrix(jacobian, NUM_VIEW_PARMS);
- FreeMatrix(corrections, 1);
- }
-
- measure_errors( datapts, view_parms, errors, rootmeansqr )
- ViewData *datapts;
- Matrix errors;
- ViewParms *view_parms;
- double *rootmeansqr;
- {
- int i;
- double sqrs=0.0;
- Point2 screenpt;
-
- for (i = 0; i < datapts->numpts; i++)
- {
- screen_project( &datapts->pts[i], view_parms, &screenpt );
- errors[0][i*2 + 0] = screenpt.x - datapts->scrpts[i].x;
- errors[0][i*2 + 1] = screenpt.y - datapts->scrpts[i].y;
- sqrs += SQR(errors[0][i*2 + 0]) + SQR(errors[0][i*2 + 1]);
- }
- *rootmeansqr = sqrt( sqrs / (datapts->numpts*2.0) );
- }
-
- build_jacobian( datapts, view_parms, jacobian )
- ViewData *datapts;
- Matrix jacobian;
- ViewParms *view_parms;
- {
- int i;
- Point3 xyz, eR;
-
- /* The jacobian matrix has at least 10 columns (u and v for 5 pts)
- * and 10 rows (10 iteration parameters). The iteration parameters will
- * be ordered: eRx eRy eRz phi_x phi_y phi_z ds xcenter ycenter aspect
- * from the top down.
- */
-
- V3MulPointByMatrix(&view_parms->eye, &view_parms->view, &eR);
- for (i = 0; i < datapts->numpts; i++)
- {
- V3MulPointByMatrix(&datapts->pts[i], &view_parms->view, &xyz);
-
- store_u_partials( &xyz, &eR, view_parms, i, jacobian );
- store_v_partials( &xyz, &eR, view_parms, i, jacobian );
- }
- }
-
- store_u_partials( xyz, eR, view_parms, ptnum, jacobian )
- Point3 *xyz, *eR;
- Matrix jacobian;
- ViewParms *view_parms;
- int ptnum;
- {
- double x_min_eR, z_min_eR;
- int i2;
-
- i2 = ptnum*2;
- x_min_eR = xyz->x - eR->x;
- z_min_eR = xyz->z - eR->z;
-
- jacobian[0][i2] = view_parms->d_over_s * view_parms->halfx / z_min_eR;
- jacobian[1][i2] = 0.0;
- jacobian[2][i2] = - view_parms->d_over_s * view_parms->halfx * x_min_eR
- / SQR( z_min_eR );
-
- jacobian[3][i2] = view_parms->d_over_s * view_parms->halfx * xyz->y
- * x_min_eR / SQR( z_min_eR );
- jacobian[4][i2] = - (view_parms->d_over_s * view_parms->halfx * xyz->z
- / z_min_eR)
- - (view_parms->d_over_s * view_parms->halfx * xyz->x * x_min_eR
- / SQR( z_min_eR ));
- jacobian[5][i2] = view_parms->d_over_s * view_parms->halfx * xyz->y
- / z_min_eR;
-
- jacobian[6][i2] = - view_parms->halfx * x_min_eR / z_min_eR;
- jacobian[7][i2] = 1.0;
- jacobian[8][i2] = 0.0;
- #ifdef ITERATE_ASPECT_RATIO
- jacobian[9][i2] = 0.0;
- #endif
- }
-
- store_v_partials( xyz, eR, view_parms, ptnum, jacobian )
- Point3 *xyz, *eR;
- Matrix jacobian;
- ViewParms *view_parms;
- int ptnum;
- {
- double y_min_eR, z_min_eR, d_over_s;
- int i2;
-
- i2 = ptnum*2 + 1;
- y_min_eR = xyz->y - eR->y;
- z_min_eR = xyz->z - eR->z;
- d_over_s = view_parms->d_over_s * view_parms->aspect;
-
- jacobian[0][i2] = 0.0;
- jacobian[1][i2] = d_over_s * view_parms->halfx / z_min_eR;
- jacobian[2][i2] = - d_over_s * view_parms->halfx * y_min_eR
- / SQR( z_min_eR );
-
- jacobian[3][i2] = (d_over_s * view_parms->halfx * xyz->z
- / z_min_eR)
- + (d_over_s * view_parms->halfx * xyz->y * y_min_eR
- / SQR( z_min_eR ));
- jacobian[4][i2] = - d_over_s * view_parms->halfx * xyz->x
- * y_min_eR / SQR( z_min_eR );
- jacobian[5][i2] = - d_over_s * view_parms->halfx * xyz->x
- / z_min_eR;
-
- jacobian[6][i2] = - view_parms->aspect * view_parms->halfx * y_min_eR
- / z_min_eR;
- jacobian[7][i2] = 0.0;
- jacobian[8][i2] = 1.0;
- #ifdef ITERATE_ASPECT_RATIO
- jacobian[9][i2] = - view_parms->d_over_s * view_parms->halfx * y_min_eR
- / z_min_eR;
- #endif
- }
-
- find_corrections( datapts, jacobian, errors, corrections )
- ViewData *datapts;
- Matrix jacobian, errors, corrections;
- {
- Matrix jacobian_transpose, combo_inverse, error_J_transpose;
- int i;
-
- /* The corrections matrix is the error matrix times the inverse
- * of the Jacobian. Since the Jacobian may not be square, the
- * pseudo-inverse is used:
- * -1 T T -1
- * C = E J = E J (J J )
- */
- for (i = 0; i < NUM_VIEW_PARMS; i++)
- corrections[0][i] = 0.0;
-
- jacobian_transpose = NewMatrix(NUM_VIEW_PARMS, datapts->numpts*2);
- combo_inverse = NewMatrix(NUM_VIEW_PARMS, NUM_VIEW_PARMS);
-
- TransposeMatrix( jacobian, jacobian_transpose,
- NUM_VIEW_PARMS, datapts->numpts*2 );
- MultMatrix( jacobian, jacobian_transpose, combo_inverse,
- NUM_VIEW_PARMS, datapts->numpts*2, NUM_VIEW_PARMS );
- if (InvertMatrix( combo_inverse, NUM_VIEW_PARMS ) == 0.0)
- {
- fprintf(stderr,"Could not invert matrix in iteration!!!\n");
- FreeMatrix(jacobian_transpose, datapts->numpts*2);
- FreeMatrix(combo_inverse, NUM_VIEW_PARMS);
- return;
- }
-
- error_J_transpose = NewMatrix(NUM_VIEW_PARMS, 1);
- MultMatrix( errors, jacobian_transpose, error_J_transpose, 1,
- datapts->numpts*2, NUM_VIEW_PARMS );
- MultMatrix( error_J_transpose, combo_inverse, corrections, 1,
- NUM_VIEW_PARMS, NUM_VIEW_PARMS );
- FreeMatrix(jacobian_transpose, datapts->numpts*2);
- FreeMatrix(combo_inverse, NUM_VIEW_PARMS);
- FreeMatrix(error_J_transpose, 1);
- }
-
- apply_corrections( corrections, view_parms )
- Matrix corrections;
- ViewParms *view_parms;
- {
- ViewParms current_parms;
- Point3 eR;
- Matrix3 inc_rotate;
-
- current_parms = *view_parms;
-
- build_rotate(&inc_rotate,
- -corrections[0][3], -corrections[0][4], -corrections[0][5]);
- V2MatMul(¤t_parms.view, &inc_rotate, &view_parms->view);
- propagate_rotate_change( view_parms );
-
- V3MulPointByMatrix(¤t_parms.eye, ¤t_parms.view, &eR);
- eR.x -= corrections[0][0];
- eR.y -= corrections[0][1];
- eR.z -= corrections[0][2];
- V3MulPointByMatrix(&eR, &view_parms->viewinv, &view_parms->eye);
- view_parms->d_over_s -= corrections[0][6];
- view_parms->xcenter -= corrections[0][7];
- view_parms->ycenter -= corrections[0][8];
- #ifdef ITERATE_ASPECT_RATIO
- view_parms->aspect -= corrections[0][9];
- #endif
- return;
- }
-
- propagate_rotate_change( view_parms )
- ViewParms *view_parms;
- {
- /* inverse is just the transpose of a rotate matrix */
- TransposeMatrix3(&view_parms->view, &view_parms->viewinv);
- }
-
- rotate_mat(m, rot_angle, pos_sin_index, neg_sin_index)
- Matrix3 *m;
- double rot_angle;
- int pos_sin_index, neg_sin_index;
- {
- double cos_theta, sin_theta;
- int i,j;
-
- cos_theta = cos( rot_angle ); sin_theta = sin( rot_angle );
- for (i = 0; i < 3; i++)
- for (j = 0; j < 3; j++)
- m->element[i][j] = (i==j) ? 1.0 : 0.0;
- m->element[pos_sin_index][pos_sin_index] = cos_theta;
- m->element[neg_sin_index][neg_sin_index] = cos_theta;
- m->element[pos_sin_index][neg_sin_index] = sin_theta;
- m->element[neg_sin_index][pos_sin_index] = -sin_theta;
- }
-
- build_rotate( m, rot_x, rot_y, rot_z )
- Matrix3 *m;
- double rot_x, rot_y, rot_z;
- {
- Matrix3 tmpmat, rotate;
-
- /* m = Xrotate
- * tmpmat = [m] [Yrotate]
- * m = [tmpmat] [Zrotate]
- */
-
- rotate_mat(m, rot_x, 1, 2);
- rotate_mat(&rotate, rot_y, 2, 0);
- V2MatMul(m, &rotate, &tmpmat);
- rotate_mat(&rotate, rot_z, 0, 1);
- V2MatMul(&tmpmat, &rotate, m);
- }
-
- screen_project(datapt, view_parms, screenpt)
- Point3 *datapt;
- ViewParms *view_parms;
- Point2 *screenpt;
- {
- Point3 xyz, data_minus_eye;
- int i;
-
- V3Sub(datapt, &view_parms->eye, &data_minus_eye);
- V3MulPointByMatrix(&data_minus_eye, &view_parms->view, &xyz);
- screenpt->x = - (view_parms->d_over_s * view_parms->halfx * xyz.x
- / xyz.z) + view_parms->xcenter;
- screenpt->y = - (view_parms->aspect * view_parms->d_over_s
- * view_parms->halfx * xyz.y
- / xyz.z) + view_parms->ycenter;
- }
-
-